4.1 Creating Gant Scripts
4.2 Re-using Grails scripts
4.3 Hooking into Events
4.4 Customising the build
4.5 Ant and Maven
Grails' command line system is built on Gant - a simple Groovy wrapper around Apache Ant.

However, Grails takes it a bit further through the use of convention and the grails command. When you type:

grails [command name]
Grails does a search in the following directories for Gant scripts to execute:

Grails will also convert command names that are in lower case form such as run-app into camel case. So typing

grails run-app

Results in a search for the following files:

If multiple matches are found Grails will give you a choice of which one to execute. When Grails executes a Gant script, it invokes the "default" target defined in that script. If there is no default, Grails will quit with an error.

To get a list and some help about the available commands type:

grails help

Which outputs usage instructions and the list of commands Grails is aware of:

Usage (optionals marked with *): 
grails [environment]* [target] [arguments]*

Examples: grails dev run-app grails create-app books

Available Targets (type grails help 'target-name' for more info): grails bootstrap grails bug-report grails clean grails compile ...

Refer to the Command Line reference in left menu of the reference guide for more information about individual commands

4.1 Creating Gant Scripts

You can create your own Gant scripts by running the create-script command from the root of your project. For example the following command:

grails create-script compile-sources

Will create a script called scripts/CompileSources.groovy. A Gant script itself is similar to a regular Groovy script except that it supports the concept of "targets" and dependencies between them:

target(default:"The default target is the one that gets executed by Grails") {
	depends(clean, compile)
}
target(clean:"Clean out things") {
	ant.delete(dir:"output")
}
target(compile:"Compile some sources") {
	ant.mkdir(dir:"mkdir")
	ant.javac(srcdir:"src/java", destdir:"output")
}

As demonstrated in the script above, there is an implicit ant variable that allows access to the Apache Ant API.

In previous versions of Grails (1.0.3 and below), the variable was Ant, i.e. with a capital first letter.

You can also "depend" on other targets using the depends method demonstrated in the default target above.

The default target

In the example above, we specified a target with the explicit name "default". This is one way of defining the default target for a script. An alternative approach is to use the setDefaultTarget() method:

target("clean-compile": "Performs a clean compilation on the app's source files.") {
	depends(clean, compile)
}
target(clean:"Clean out things") {
	ant.delete(dir:"output")
}
target(compile:"Compile some sources") {
	ant.mkdir(dir:"mkdir")
	ant.javac(srcdir:"src/java", destdir:"output")
}

setDefaultTarget("clean-compile")

This allows you to call the default target directly from other scripts if you wish. Also, although we have put the call to setDefaultTarget() at the end of the script in this example, it can go anywhere as long as it comes after the target it refers to ("clean-compile" in this case).

Which approach is better? To be honest, you can use whichever you prefer - there don't seem to be any major advantages in either case. One thing we would say is that if you want to allow other scripts to call your "default" target, you should move it into a shared script that doesn't have a default target at all. We'll talk some more about this in the next section.

4.2 Re-using Grails scripts

Grails ships with a lot of command line functionality out of the box that you may find useful in your own scripts (See the command line reference in the reference guide for info on all the commands). Of particular use are the compile, package and bootstrap scripts.

The bootstrap script for example allows you to bootstrap a Spring ApplicationContext instance to get access to the data source and so on (the integration tests use this):

includeTargets << grailsScript("_GrailsBootstrap")

target ('default': "Load the Grails interactive shell") { depends( configureProxy, packageApp, classpath, loadApp, configureApp )

Connection c try { // do something with connection c = appCtx.getBean('dataSource').getConnection() } finally { c?.close() } }

Pulling in targets from other scripts

Gant allows you to pull in all targets (except "default") from another Gant script. You can then depend upon or invoke those targets as if they had been defined in the current script. The mechanism for doing this is the includeTargets property. Simply "append" a file or class to it using the left-shift operator:

includeTargets << new File("/path/to/my/script.groovy")
includeTargets << gant.tools.Ivy
Don't worry too much about the syntax using a class, it's quite specialised. If you're interested, look into the Gant documentation.

Core Grails targets

As you saw in the example at the beginning of this section, you use neither the File- nor the class-based syntax for includeTargets when including core Grails targets. Instead, you should use the special grailsScript() method that is provided by the Grails command launcher (note that this is not available in normal Gant scripts, just Grails ones).

The syntax for the grailsScript() method is pretty straightforward: simply pass it the name of the Grails script you want to include, without any path information. Here is a list of Grails scripts that you may want to re-use:
ScriptDescription
_GrailsSettingsYou really should include this! Fortunately, it is included automatically by all other Grails scripts bar one (_GrailsProxy), so you usually don't have to include it explicitly.
_GrailsEventsIf you want to fire events, you need to include this. Adds an event(String eventName, List args) method. Again, included by almost all other Grails scripts.
_GrailsClasspathSets up compilation, test, and runtime classpaths. If you want to use or play with them, include this script. Again, included by almost all other Grails scripts.
_GrailsProxyIf you want to access the internet, include this script so that you don't run into problems with proxies.
_GrailsArgParsingProvides a parseArguments target that does what it says on the tin: parses the arguments provided by the user when they run your script. Adds them to the argsMap property.
_GrailsTestContains all the shared test code. Useful if you want to add any extra tests.
_GrailsRunProvides all you need to run the application in the configured servlet container, either normally (runApp/runAppHttps) or from a WAR file (runWar/runWarHttps).

There are many more scripts provided by Grails, so it is worth digging into the scripts themselves to find out what kind of targets are available. Anything that starts with an "_" is designed for re-use.

In pre-1.1 versions of Grails, the "_Grails..." scripts were not available. Instead, you typically include the corresponding command script, for example "Init.groovy" or "Bootstrap.groovy".

Also, in pre-1.0.4 versions of Grails you cannot use the grailsScript() method. Instead, you must use includeTargets << new File(...) and specify the script's location in full (i.e. $GRAILS_HOME/scripts).

Script architecture

You maybe wondering what those underscores are doing in the names of the Grails scripts. That is Grails' way of determining that a script is _internal_, or in other words that it has not corresponding "command". So you can't run "grails _grails-settings" for example. That is also why they don't have a default target.

Internal scripts are all about code sharing and re-use. In fact, we recommend you take a similar approach in your own scripts: put all your targets into an internal script that can be easily shared, and provide simple command scripts that parse any command line arguments and delegate to the targets in the internal script. Say you have a script that runs some functional tests - you can split it like this:

./scripts/FunctionalTests.groovy:

includeTargets << new File("${basedir}/scripts/_FunctionalTests.groovy")

target(default: "Runs the functional tests for this project.") { depends(runFunctionalTests) }

./scripts/_FunctionalTests.groovy:

includeTargets << grailsScript("_GrailsTest")

target(runFunctionalTests: "Run functional tests.") { depends(...) … }

Here are a few general guidelines on writing scripts:

4.3 Hooking into Events

Grails provides the ability to hook into scripting events. These are events triggered during execution of Grails target and plugin scripts.

The mechanism is deliberately simple and loosely specified. The list of possible events is not fixed in any way, so it is possible to hook into events triggered by plugin scripts, for which there is no equivalent event in the core target scripts.

Defining event handlers

Event handlers are defined in scripts called _Events.groovy. Grails searches for these scripts in the following locations:

Whenever an event is fired, all the registered handlers for that event are executed. Note that the registration of handlers is performed automatically by Grails, so you just need to declare them in the relevant _Events.groovy file.

In versions of Grails prior to 1.0.4, the script was called Events.groovy, that is without the leading underscore.

Event handlers are blocks defined in _Events.groovy, with a name beginning with "event". The following example can be put in your /scripts directory to demonstrate the feature:

eventCreatedArtefact = { type, name ->
   println "Created $type $name"
}

eventStatusUpdate = { msg -> println msg }

eventStatusFinal = { msg -> println msg }

You can see here the three handlers eventCreatedArtefact, eventStatusUpdate, eventStatusFinal. Grails provides some standard events, which are documented in the command line reference guide. For example the compile command fires the following events:

Triggering events

To trigger an event simply include the Init.groovy script and call the event() closure:

includeTargets << grailsScript("_GrailsEvents")

event("StatusFinal", ["Super duper plugin action complete!"])

Common Events

Below is a table of some of the common events that can be leveraged:

EventParametersDescription
StatusUpdatemessagePassed a string indicating current script status/progress
StatusErrormessagePassed a string indicating an error message from the current script
StatusFinalmessagePassed a string indicating the final script status message, i.e. when completing a target, even if the target does not exit the scripting environment
CreatedArtefactartefactType,artefactNameCalled when a create-xxxx script has completed and created an artefact
CreatedFilefileNameCalled whenever a project source filed is created, not including files constantly managed by Grails
ExitingreturnCodeCalled when the scripting environment is about to exit cleanly
PluginInstalledpluginNameCalled after a plugin has been installed
CompileStartkindCalled when compilation starts, passing the kind of compile - source or tests
CompileEndkindCalled when compilation is finished, passing the kind of compile - source or tests
DocStartkindCalled when documentation generation is about to start - javadoc or groovydoc
DocEndkindCalled when documentation generation has ended - javadoc or groovydoc
SetClasspathrootLoaderCalled during classpath initialization so plugins can augment the classpath with rootLoader.addURL(...). Note that this augments the classpath after event scripts are loaded so you cannot use this to load a class that your event script needs to import, although you can do this if you load the class by name.
PackagingEndnoneCalled at the end of packaging (which is called prior to the Tomcat server being started and after web.xml is generated)

4.4 Customising the build

Grails is most definitely an opinionated framework and it prefers convention to configuration, but this doesn't mean you can't configure it. In this section, we look at how you can influence and modify the standard Grails build.

The defaults

In order to customise a build, you first need to know what you can customise. The core of the Grails build configuration is the grails.util.BuildSettings class, which contains quite a bit of useful information. It controls where classes are compiled to, what dependencies the application has, and other such settings.

Here is a selection of the configuration options and their default values:
PropertyConfig optionDefault value
grailsWorkDirgrails.work.dir$USER_HOME/.grails/<grailsVersion>
projectWorkDirgrails.project.work.dir<grailsWorkDir>/projects/<baseDirName>
classesDirgrails.project.class.dir<projectWorkDir>/classes
testClassesDirgrails.project.test.class.dir<projectWorkDir>/test-classes
testReportsDirgrails.project.test.reports.dir<projectWorkDir>/test/reports
resourcesDirgrails.project.resource.dir<projectWorkDir>/resources
projectPluginsDirgrails.plugins.dir<projectWorkDir>/plugins
globalPluginsDirgrails.global.plugins.dir<grailsWorkDir>/global-plugins
verboseCompilegrails.project.compile.verbosefalse

The BuildSettings class has some other properties too, but they should be treated as read-only:
PropertyDescription
baseDirThe location of the project.
userHomeThe user's home directory.
grailsHomeThe location of the Grails installation in use (may be null).
grailsVersionThe version of Grails being used by the project.
grailsEnvThe current Grails environment.
compileDependenciesA list of compile-time project dependencies as File instances.
testDependenciesA list of test-time project dependencies as File instances.
runtimeDependenciesA list of runtime-time project dependencies as File instances.

Of course, these properties aren't much good if you can't get hold of them. Fortunately that's easy to do: an instance of BuildSettings is available to your scripts via the grailsSettings script variable. You can also access it from your code by using the grails.util.BuildSettingsHolder class, but this isn't recommended.

Overriding the defaults

All of the properties in the first table can be overridden by a system property or a configuration option - simply use the "config option" name. For example, to change the project working directory, you could either run this command:

grails -Dgrails.project.work.dir=work compile
or add this option to your grails-app/conf/BuildConfig.groovy file:
grails.project.work.dir = "work"
Note that the default values take account of the property values they depend on, so setting the project working directory like this would also relocate the compiled classes, test classes, resources, and plugins.

What happens if you use both a system property and a configuration option? Then the system property wins because it takes precedence over the BuildConfig.groovy file, which in turn takes precedence over the default values.

The BuildConfig.groovy file is a sibling of grails-app/conf/Config.groovy - the former contains options that only affect the build, whereas the latter contains those that affect the application at runtime. It's not limited to the options in the first table either: you will find build configuration options dotted around the documentation, such as ones for specifying the port that the embedded servlet container runs on or for determining what files get packaged in the WAR file.

Available build settings

NameDescription
grails.server.port.httpPort to run the embedded servlet container on ("run-app" and "run-war"). Integer.
grails.server.port.httpsPort to run the embedded servlet container on for HTTPS ("run-app https" and "run-war https"). Integer.
grails.config.base.webXmlPath to a custom web.xml file to use for the application (alternative to using the web.xml template).
grails.compiler.dependenciesLegacy approach to adding extra dependencies to the compiler classpath. Set it to a closure containing "fileset()" entries.
grails.testing.patternsA list of Ant path patterns that allow you to control which files are included in the tests. The patterns should not include the test case suffix, which is set by the next property.
grails.testing.nameSuffixBy default, tests are assumed to have a suffix of "Tests". You can change it to anything you like but setting this option. For example, another common suffix is "Test".
grails.war.destFileA string containing the file path of the generated WAR file, along with its full name (include extension). For example, "target/my-app.war".
grails.war.dependenciesA closure containing "fileset()" entries that allows you complete control over what goes in the WAR's "WEB-INF/lib" directory.
grails.war.copyToWebAppA closure containing "fileset()" entries that allows you complete control over what goes in the root of the WAR. It overrides the default behaviour of including everything under "web-app".
grails.war.resourcesA closure that takes the location of the staging directory as its first argument. You can use any Ant tasks to do anything you like. It is typically used to remove files from the staging directory before that directory is jar'd up into a WAR.
grails.project.web.xmlThe location to generate Grails' web.xml to

4.5 Ant and Maven

If all the other projects in your team or company are built using a standard build tool such as Ant or Maven, you become the black sheep of the family when you use the Grails command line to build your application. Fortunately, you can easily integrate the Grails build system into the main build tools in use today (well, the ones in use in Java projects at least).

Ant Integration

When you create a Grails application via the create-app command, Grails automatically creates an Apache Ant build.xml file for you containing the following targets:

Each of these can be run by Ant, for example:

ant war

The build file is all geared up to use Apache Ivy for dependency management, which means that it will automatically download all the requisite Grails JAR files and other dependencies on demand. You don't even have to install Grails locally to use it! That makes it particularly useful for continuous integration systems such as CruiseControl or Hudson

It uses the Grails Ant task to hook into the existing Grails build system. The task allows you to run any Grails script that's available, not just the ones used by the generated build file. To use the task, you must first declare it:

<taskdef name="grailsTask"
         classname="grails.ant.GrailsTask"
         classpathref="grails.classpath"/>

This raises the question: what should be in "grails.classpath"? The task itself is in the "grails-bootstrap" JAR artifact, so that needs to be on the classpath at least. You should also include the "groovy-all" JAR. With the task defined, you just need to use it! The following table shows you what attributes are available:
AttributeDescriptionRequired
homeThe location of the Grails installation directory to use for the build.Yes, unless classpath is specified.
classpathrefClasspath to load Grails from. Must include the "grails-bootstrap" artifact and should include "grails-scripts".Yes, unless home is set or you use a classpath element.
scriptThe name of the Grails script to run, e.g. "TestApp".Yes.
argsThe arguments to pass to the script, e.g. "-unit -xml".No. Defaults to "".
environmentThe Grails environment to run the script in.No. Defaults to the script default.
includeRuntimeClasspathAdvanced setting: adds the application's runtime classpath to the build classpath if true.No. Defaults to true.

The task also supports the following nested elements, all of which are standard Ant path structures:

How you populate these paths is up to you. If you are using the home attribute and put your own dependencies in the lib directory, then you don't even need to use any of them. For an example of their use, take a look at the generated Ant build file for new apps.

Maven Integration

From 1.1 onwards, Grails provides integration with Maven 2 via a Maven plugin. The current Maven plugin is based on, but effectively supercedes, the version created by Octo, who did a great job.

Preparation

In order to use the new plugin, all you need is Maven 2 installed and set up. This is because you no longer need to install Grails separately to use it with Maven!

The Maven 2 integration for Grails has been designed and tested for Maven 2.0.9 and above. It will not work with earlier versions.

To make life easier for you, we do recommend that you add a plugin group for Grails to your Maven settings file ( $USER_HOME/.m2/settings.xml ):

<settings><pluginGroups>
    <pluginGroup>org.grails</pluginGroup>
  </pluginGroups>
</settings>

In addition, if you have the Octo Maven Tools for Grails set up then you'll need to remove the com.octo.mtg plugin group.

Creating a Grails Maven Project

To create a Mavenized Grails project simple run the following command:

mvn archetype:generate -DarchetypeGroupId=org.grails \
    -DarchetypeArtifactId=grails-maven-archetype \
    -DarchetypeVersion=1.0 \
    -DarchetypeRepository=http://snapshots.repository.codehaus.org \
    -DgroupId=example -DartifactId=my-app

Choose whichever group ID and artifact ID you want for your application, but everything else must be as written. This will create a new Maven project with a POM and a couple of other files. What you won't see is anything that looks like a Grails application. So, the next step is to create the project structure that you're used to:

cd my-app
mvn initialize

Now you have a Grails application all ready to go. The plugin integrates into the standard build cycle, so you can use the standard Maven phases to build and package your app: mvn clean , mvn compile , mvn test , mvn package .

You can also take advantage of some of the Grails commands that have been wrapped as Maven goals:

Mavenizing an existing project

Creating a new project is great way to start, but what if you already have one? You don't want to create a new project and then copy the contents of the old one over. The solution is to create a POM for the existing project using this Maven command:

mvn grails:create-pom -DgroupId=com.mycompany
When this command has finished, you can immediately start using the standard phases, such as mvn package. Note that you have to specify a group ID when creating the POM.

Adding Grails commands to phases

The standard POM created for you by Grails already attaches the appropriate core Grails commands to their corresponding build phases, so "compile" goes in the "compile" phase and "war" goes in the "package" phase. That doesn't help though when you want to attach a plugin's command to a particular phase. The classic example is functional tests. How do you make sure that your functional tests (using which ever plugin you have decided on) are run during the "integration-test" phase?

Fear not: all things are possible. In this case, you can associate the command to a phase using an extra "execution" block:

<plugin>
        <groupId>org.grails</groupId>
        <artifactId>grails-maven-plugin</artifactId>
        <version>1.0-SNAPSHOT</version>
        <extensions>true</extensions>
        <executions>
          <execution>
            <goals></goals>
          </execution>
          <!-- Add the "functional-tests" command to the "integration-test" phase -->
          <execution>
            <id>functional-tests</id>
            <phase>integration-test</phase>
            <goals>
              <goal>exec</goal>
            </goals>
            <configuration>
              <command>functional-tests</command>
            </configuration>
          </execution>
        </executions>
      </plugin>

This also demonstrates the grails:exec goal, which can be used to run any Grails command. Simply pass the name of the command as the command system property, and optionally specify the arguments via the args property:

mvn grails:exec -Dcommand=create-webtest -Dargs=Book